/**
 * @file integer_traits.hpp
 * @putpose define some generic traits for using with uintegers
 */

#ifndef __BIG_INTEGER_TRAITS_HPP__
#define __BIG_INTEGER_TRAITS_HPP__

#include <string>
#include <vector>

BIG_NUMBERS_NAMESPACE_BEGIN

template <typename digit_type, typename char_t>
struct integer_char_traits
{
        typedef char_t char_type;
        typedef std::basic_string<char_type> string;

        static char_type to_char(digit_type i)
        {
                return char(i + '0');
        }
        static digit_type from_char(char_type c)
        {
                return c - '0';
        }
};

template <typename digit_type, typename container_t,
          typename double_digit_type, int base,
          typename char_t, typename char_traits_t=integer_char_traits<digit_type, char_t> >
struct integer_traits
{
        typedef digit_type digit;
        typedef double_digit_type double_digit;
        typedef container_t base_type;

        typedef char_traits_t char_traits;
        typedef typename char_traits::char_type char_type;
        typedef typename char_traits::string string;

        typedef std::vector<digit> digits;

        static const double_digit end_digit = base;
        static const digit max_digit = (digit)(base - 1);

        static bool is_digit(digit d)
        {
                return d <= max_digit;
        }
};

template <typename digit_type, typename container_t,
          typename double_digit_type,
          typename char_t, typename char_traits_t>
struct integer_traits<digit_type, container_t, double_digit_type,
                      (double_digit_type)((digit_type)-1) + 1,
                      char_t, char_traits_t>
{
        typedef digit_type digit;
        typedef double_digit_type double_digit;
        typedef container_t base_type;

        typedef char_traits_t char_traits;
        typedef typename char_traits::char_type char_type;
        typedef typename char_traits::string string;

        typedef std::vector<digit> digits;

        static const digit max_digit = (digit_type)-1;
        static const double_digit end_digit = ((double_digit)max_digit) + 1;

        static bool is_digit(digit d)
        {
                return true;
        }
};

BIG_NUMBERS_NAMESPACE_END

#endif // __BIG_INTEGER_TRAITS_HPP__
